package com.nc.mem.tests.custom.map;

import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;

import org.testng.Assert;

import com.nc.mem.serial.graph.cust.KeyOnlyPayload;
import com.nc.mem.serial.graph.cust.NotNullNonPolymorphic;
import com.nc.mem.serial.graph.cust.Serializable;
import com.nc.mem.serial.graph.cust.ValOnlyPayload;

@Serializable(include = "*")
public class C extends AbstractMapSource {

	static class C0 implements Comparator<String> {

		@Override
		public int compare(final String left, final String right) {
			return right.compareTo(left);
		}
	}

	static class C1 implements Comparator<String> {

		@Override
		public int compare(final String left, final String right) {
			return right.compareTo(left);
		}
	}

	class C2 implements Comparator<String> {

		@Override
		public int compare(final String left, final String right) {
			return right.compareTo(left);
		}
	}

	class C3 implements Comparator<String> {

		Comparator<String> c = this;

		@Override
		public int compare(final String left, final String right) {
			return right.compareTo(left);
		}
	}

	static Comparator<String> C4 = new Comparator<String>() {

		@Override
		public int compare(final String left, final String right) {
			return left.compareTo(right);
		}
	};

	static Comparator<String> C5 = new Comparator<String>() {

		Comparator<String> c;

		{
			c = this;
		}

		@Override
		public int compare(final String left, final String right) {
			if (c != this) {
				return c.compare(left, right);
			}
			return left.compareTo(right);
		}
	};

	Comparator<String> C3 = new Comparator<String>() {

		@Override
		public int compare(final String left, final String right) {
			return left.compareTo(right);
		}
	};

	Map<String, A> cacheA = new TreeMap<String, A>(new C0());

	@NotNullNonPolymorphic
	Map<String, A> cacheB = new TreeMap<String, A>(new C0());

	@NotNullNonPolymorphic
	@KeyOnlyPayload
	Map<String, A> cacheC = new TreeMap<String, A>(new C0());

	@NotNullNonPolymorphic
	@ValOnlyPayload
	Map<String, A> cacheD = new TreeMap<String, A>(new C0());

	@NotNullNonPolymorphic
	@KeyOnlyPayload
	@ValOnlyPayload
	Map<String, A> cacheE = new TreeMap<String, A>(new C0());

	Map<String, A> cacheF = new TreeMap<String, A>(new C1());

	@NotNullNonPolymorphic
	Map<String, A> cacheG = new TreeMap<String, A>(new C1());

	@NotNullNonPolymorphic
	@KeyOnlyPayload
	Map<String, A> cacheH = new TreeMap<String, A>(new C1());

	@NotNullNonPolymorphic
	@ValOnlyPayload
	Map<String, A> cacheI = new TreeMap<String, A>(new C1());

	@NotNullNonPolymorphic
	@KeyOnlyPayload
	@ValOnlyPayload
	Map<String, A> cacheJ = new TreeMap<String, A>(new C1());

	Map<String, A> cacheK = new TreeMap<String, A>(new C2());

	@NotNullNonPolymorphic
	Map<String, A> cacheL = new TreeMap<String, A>(new C2());

	@NotNullNonPolymorphic
	@KeyOnlyPayload
	Map<String, A> cacheM = new TreeMap<String, A>(new C2());

	@NotNullNonPolymorphic
	@ValOnlyPayload
	Map<String, A> cacheN = new TreeMap<String, A>(new C2());

	@NotNullNonPolymorphic
	@KeyOnlyPayload
	@ValOnlyPayload
	Map<String, A> cacheO = new TreeMap<String, A>(new C2());

	Map<String, A> cacheP = new TreeMap<String, A>(new C3());

	@NotNullNonPolymorphic
	Map<String, A> cacheQ = new TreeMap<String, A>(new C3());

	@NotNullNonPolymorphic
	@KeyOnlyPayload
	Map<String, A> cacheR = new TreeMap<String, A>(new C3());

	@NotNullNonPolymorphic
	@ValOnlyPayload
	Map<String, A> cacheS = new TreeMap<String, A>(new C3());

	@NotNullNonPolymorphic
	@KeyOnlyPayload
	@ValOnlyPayload
	Map<String, A> cacheT = new TreeMap<String, A>(new C3());

	Map<String, A> cacheU = new TreeMap<String, A>(C4);

	@NotNullNonPolymorphic
	Map<String, A> cacheV = new TreeMap<String, A>(C4);

	@NotNullNonPolymorphic
	@KeyOnlyPayload
	Map<String, A> cacheW = new TreeMap<String, A>(C4);

	@NotNullNonPolymorphic
	@ValOnlyPayload
	Map<String, A> cacheX = new TreeMap<String, A>(C4);

	@NotNullNonPolymorphic
	@KeyOnlyPayload
	@ValOnlyPayload
	Map<String, A> cacheY = new TreeMap<String, A>(C4);

	Map<String, A> cacheZ = new TreeMap<String, A>(C5);

	@NotNullNonPolymorphic
	Map<String, A> cacheAA = new TreeMap<String, A>(C5);

	@NotNullNonPolymorphic
	@KeyOnlyPayload
	Map<String, A> cacheAB = new TreeMap<String, A>(C5);

	@NotNullNonPolymorphic
	@ValOnlyPayload
	Map<String, A> cacheAC = new TreeMap<String, A>(C5);

	@NotNullNonPolymorphic
	@KeyOnlyPayload
	@ValOnlyPayload
	Map<String, A> cacheAD = new TreeMap<String, A>(C5);

	public void assertAllCachesSized(final int i) {
		for (final Map<?, ?> m : getAllCaches()) {
			Assert.assertEquals(i, m.size());
		}
	}

	@Override
	public boolean equals(final Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (getClass() != obj.getClass()) {
			return false;
		}
		final C other = (C) obj;

		final Map<?, ?>[] maps = getAllCaches();
		final Map<?, ?>[] otherMaps = other.getAllCaches();

		for (int i = 0; i < maps.length; i++) {
			if (!maps[i].equals(otherMaps[i])) {
				return false;
			}
		}

		return true;

	}

	@SuppressWarnings("unchecked")
	public void fill(final Iterable<A> itr) {
		final Map<?, ?>[] caches = getAllCaches();
		for (final A a : itr) {
			for (@SuppressWarnings("rawtypes")
			final Map map : caches) {
				map.put(a.id, a);
				map.put(a.id + "clone", a.clone());
			}
		}
	}

	@Override
	public int hashCode() {
		return 0;
	}

}
